﻿using System;
using System.Globalization;
using System.Collections.Generic;
using System.Text.RegularExpressions;
using System.IO;
using System.Windows.Forms;
namespace System
{
	public partial struct V3G
	{
		bool DoTess(bool CutTriangles)
		{
			int N = 0;
			while (TriPoints.Count > 2)
			{
				if (TriPoints.Count == 3)
				{
					Log("Last Iteration");
					Triangles.Add(new Triangle3G(TriPoints[0], TriPoints[1], TriPoints[2]));
					return true;
				}
				else
				{
					if (CutTriangles)
						RemoveLongSides();
					bool Convex = false;
					Triangle3G T = new Triangle3G();
					int M = 0;
					while (!Convex)
					{
						if (M >= TriPoints.Count)
							return false;
						M++;
						V3G p1 = TriPoints[(N - 1 + TriPoints.Count) % TriPoints.Count];
						V3G p2 = TriPoints[N % TriPoints.Count];
						V3G p3 = TriPoints[(N + 1) % TriPoints.Count];
						T = new Triangle3G(p1, p2, p3);
						V3D t1 = new V3D(p1.Longitude, p1.Latitude, 0);
						V3D t2 = new V3D(p2.Longitude, p2.Latitude, 0);
						V3D t3 = new V3D(p3.Longitude, p3.Latitude, 0);
						V3D A = t2 - t1;
						V3D B = t3 - t2;
						Line3D L1 = new Line3D(t1, t3);
						Line3D L2 = new Line3D(t2, (t1 + t3) / 2);
						Convex = true;
						if ((A % B).Length == 0)
							Convex = false;
						/*else
							if ((CW ? -1 : 1) * ((A % B) * V3D.Blue > 0 ? 1 : -1) <= 0)
								Convex = false;*/
						for (int i = N + 2; Convex && i < (N + TriPoints.Count - 3); i++)
						{
							V3D X1 = new V3D(TriPoints[i % TriPoints.Count].Longitude, TriPoints[i % TriPoints.Count].Latitude, 0);
							V3D X2 = new V3D(TriPoints[(i + 1) % TriPoints.Count].Longitude, TriPoints[(i + 1) % TriPoints.Count].Latitude, 0);
							Line3D L = new Line3D(X1, X2);
							if ((L * L2).Valid || (L * L1).Valid)
								Convex = false;
						}
						if (!Convex)
							N = (N + 1) % TriPoints.Count;
					}

					Triangles.Add(T);
					TriPoints.RemoveAt(N % TriPoints.Count);
					N = (N + 1) % TriPoints.Count;
				}
			}
			return true;
		}
		public bool Triangularize(bool CutTriangles)
		{
			Triangles = new List<Triangle3G>();
			//TriPoints = new List<V3G>(Points.ToArray());
			GetDir();
			return DoTess(CutTriangles);
		}
		void AddTri(V3G p1, V3G p2, V3G p3)
		{
			Triangles.Add(new Triangle3G(p1, p2, p3));
		}

		void BuildRect(V3G R1, V3G R2, V3G R3, V3G R4)
		{
			bool L1 = false;
			for (int i = 0; !L1 && i < Points.Count; i++)
			{
				Line3G LB = new Line3G(Points[i], Points[(i + 1) % Points.Count], false);
				Line3G LM = new Line3G(R1, R2, false);
				if ((LB * LM).Valid || (LM * LB).Valid)
					L1 = true;
			}
			bool L2 = false;
			for (int i = 0; !L2 && i < Points.Count; i++)
			{
				Line3G LB = new Line3G(Points[i], Points[(i + 1) % Points.Count], false);
				Line3G LM = new Line3G(R2, R3, false);
				if ((LB * LM).Valid || (LM * LB).Valid)
					L2 = true;
			}
			bool L3 = false;
			for (int i = 0; !L3 && i < Points.Count; i++)
			{
				Line3G LB = new Line3G(Points[i], Points[(i + 1) % Points.Count], false);
				Line3G LM = new Line3G(R3, R4, false);
				if ((LB * LM).Valid || (LM * LB).Valid)
					L3 = true;
			}
			bool L4 = false;
			for (int i = 0; !L4 && i < Points.Count; i++)
			{
				Line3G LB = new Line3G(Points[i], Points[(i + 1) % Points.Count], false);
				Line3G LM = new Line3G(R4, R1, false);
				if ((LB * LM).Valid || (LM * LB).Valid)
					L4 = true;
			}
			if (L1 || L2 || L3 || L4)
			{
				if (R3.Longitude - R1.Longitude > 0.25)
				{
					V3G P1 = R1;
					V3G P2 = R2;
					V3G P3 = R3;
					V3G P4 = R4;
					V3G P12 = new V3G((P1.Longitude + P2.Longitude) / 2, P1.Latitude, 0);
					V3G P23 = new V3G(P2.Longitude, (P2.Latitude + P3.Latitude) / 2, 0);
					V3G P34 = new V3G((P3.Longitude + P4.Longitude) / 2, P3.Latitude, 0);
					V3G P41 = new V3G(P4.Longitude, (P4.Latitude + P1.Latitude) / 2, 0);
					V3G P13 = new V3G((P1.Longitude + P3.Longitude) / 2, (P1.Latitude + P3.Latitude) / 2, 0);
					BuildRect(P1, P12, P13, P41);
					BuildRect(P12, P2, P23, P13);
					BuildRect(P13, P23, P3, P34);
					BuildRect(P41, P13, P34, P4);
				}
			}
			else if (PointInPolygon(R1))
			{
				AddTri(R1, R2, R3);
				AddTri(R1, R3, R4);
			}
		}
		public bool SphericTriangles()
		{
			Triangles = new List<Triangle3G>();
			//TriPoints = new List<V3G>(Points.ToArray());
			GetDir();
			double MinX = Points[0].Longitude;
			double MaxX = Points[0].Longitude;
			double MinY = Points[0].Latitude;
			double MaxY = Points[0].Latitude;
			for (int i = 1; i < Points.Count; i++)
			{
				MinX = Math.Min(MinX, Points[i].Longitude);
				MaxX = Math.Max(MaxX, Points[i].Longitude);
				MinY = Math.Min(MinY, Points[i].Latitude);
				MaxY = Math.Max(MaxY, Points[i].Latitude);
			}
			V3G P1 = new V3G(MinX, MinY, 0);
			V3G P2 = new V3G(MaxX, MinY, 0);
			V3G P3 = new V3G(MaxX, MaxY, 0);
			V3G P4 = new V3G(MinX, MaxY, 0);
			BuildRect(P1, P2, P3, P4);
			return true;
		}
	}
}